#include "SCheckEx.h"

#include <core/ImageMgr.h>
#include <core/StyleMgr.h>

#include <QFontMetrics>
#include <QPaintEvent>
#include <QStylePainter>

SCheckEx::SCheckEx(const QString& v, QWidget* parent /*= nullptr*/)
    : QWidget(parent), m_text(v) {}

void SCheckEx::setSelectState(Qt::CheckState v, bool notify) {
  m_selectState = v;
  update();
  if (notify) stateChanged(m_index);
}

QSize SCheckEx::sizeHint() const {
  QSizePolicy policy = sizePolicy();
  if (policy.horizontalPolicy() == QSizePolicy::Expanding ||
      policy.horizontalPolicy() == QSizePolicy::Fixed ||
      policy.verticalPolicy() == QSizePolicy::Fixed)
    return QWidget::sizeHint();

  int gap = StyleMgr::instance().size("CtrlSpacing");
  int width = gap;
  SImage* img = ImgMgr::instance().image("widgets_check", WidgetStatus::kNormal,
                                         devicePixelRatioF());
  if (img) width += img->width() + gap;

  QFontMetrics fm(font());
  width += fm.horizontalAdvance(m_text) + gap;
  return QSize(width, StyleMgr::instance().size("ButtonHeight"));
}

void SCheckEx::mousePressEvent(QMouseEvent* e) {
  if (m_selectState == Qt::Unchecked)
    m_selectState = Qt::Checked;
  else {
    if (m_type == SelectType::Radio) return;
    m_selectState = Qt::Unchecked;
  }

  update();
  stateChanged(m_index);
}

void SCheckEx::enterEvent(QEvent* event) {
  m_hover = true;
  update();
}

void SCheckEx::leaveEvent(QEvent* event) {
  m_hover = false;
  update();
}

void SCheckEx::paintEvent(QPaintEvent* event) {
  QStylePainter painter(this);
  painter.setRenderHint(QPainter::Antialiasing);
  if (m_bSetTextBK) {
    QColor bkColor = StyleMgr::instance().color("StaticTextBK");
    painter.setBrush(bkColor);
    painter.setPen(bkColor);
    painter.drawRoundedRect(rect(), StyleMgr::instance().size("RoundCorner"),
                            StyleMgr::instance().size("RoundCorner"));
  }

  QString imageName;
  switch (m_type) {
    case SCheckEx::SelectType::Check:
      imageName = m_selectState == Qt::Checked
                      ? "widgets_check_selected"
                      : "widgets_check";  // TODO: PartiallyChecked
      break;
    case SCheckEx::SelectType::Radio:
      imageName = m_selectState == Qt::Checked ? "widgets_radio_selected"
                                               : "widgets_radio";
      break;
    case SCheckEx::SelectType::Switch:
      imageName = m_selectState == Qt::Checked ? "widgets_grid_remdon"
                                               : "widgets_grid_remdoff";
      break;
    default:
      break;
  }

  WidgetStatus status =
      isEnabled() ? (m_hover ? WidgetStatus::kHover : WidgetStatus::kNormal)
                  : WidgetStatus::kDisabled;
  SImage* img =
      ImgMgr::instance().image(imageName, status, devicePixelRatioF());
  QRect indicatorRect = rect();
  if (img) {
    int width = img->width();
    int height = img->height();
    int y = (rect().height() - height) / 2;
    indicatorRect.setRect(StyleMgr::instance().size("CtrlSpacing"), y, width,
                          height);

    painter.setRenderHint(QPainter::SmoothPixmapTransform);  // 处理图片失真
    painter.drawImage(indicatorRect, *img);
  }

  QRect txtrect = rect();
  txtrect.adjust(
      indicatorRect.right() + StyleMgr::instance().size("CtrlSpacing"), 0, 0,
      0);
  QString txtColorName =
      isEnabled()
          ? (m_selectState == Qt::Unchecked ? "TextNormal" : "Highlight")
          : "TxtDisabled";
  if (m_type == SelectType::Check && !isEnabled() &&
      m_selectState == Qt::Checked)
    txtColorName = "Highlight";
  QColor txtColor = StyleMgr::instance().color(txtColorName);
  painter.setPen(txtColor);
  painter.drawText(txtrect, m_text,
                   QTextOption(Qt::AlignVCenter | Qt::AlignLeft));
}

SRadioGroup::SRadioGroup(QObject* p) : QObject(p) {}

SCheckEx* SRadioGroup::getSCheckEx(int index) const {
  // 不设置判断，index可能会大于m_items.size()
  return m_items.find(index)->second;
}

void SRadioGroup::addRadio(SCheckEx* item) {
  if (!item) return;
  int index = item->index();
  auto iter = m_items.find(index);
  Q_ASSERT(iter == m_items.end());
  m_items[index] = item;

  connect(item, &SCheckEx::stateChanged, this, &SRadioGroup::onRadioSelect);
}

int SRadioGroup::getSCheckExCount() const { return m_items.size(); }

void SRadioGroup::onRadioSelect(int index) {
  auto iter = m_items.find(index);
  bool checked = iter->second->isSelected();
  if (!checked) return;
  for (auto iterFind = m_items.begin(); iterFind != m_items.end(); ++iterFind) {
    if (iterFind == iter) continue;
    iterFind->second->setSelectState(checked ? Qt::Unchecked : Qt::Checked);
  }
}
